#include "SphereDemo.h"
#include <vector>
#include"RenderManager.h"
#include "Camera.h"
using namespace std;
struct VertexSphere
{
	XMFLOAT4 pos;
	XMFLOAT2 UV;
};

struct ConstSphereBuffer
{
	XMMATRIX m_world;
	XMMATRIX m_view;
	XMMATRIX m_proj;
};



const int longitude = 36;
const int latitude = 36;

struct LLStruct
{
	float lat;
	float lot;
};
LLStruct LL[latitude][longitude];


SphereDemo::SphereDemo():m_pInputLayout(nullptr), m_pVertexBuffer(nullptr), m_pSolidColorPS(nullptr), m_pSolidColorVS(nullptr), g_pConstantBuffer11(nullptr)
{
}


SphereDemo::~SphereDemo()
{
	//
}

bool SphereDemo::LoadContent()
{
	ID3DBlob *vsBuffer = 0;
	bool compileResult = CompileD3DShader(L"ShaderSpher.fx", "VS_Main", "vs_4_0", &vsBuffer);
	if (!compileResult)
	{
		MessageBoxA(0, "载入顶点着色器错误", "编译错误", MB_OK);
		return false;
	}

	HRESULT result;
	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateVertexShader(vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(),
		0, &m_pSolidColorVS);

	if (FAILED(result))
	{
		if (vsBuffer)
		{
			vsBuffer->Release();
		}
		return false;
	}

	D3D11_INPUT_ELEMENT_DESC solidColorLayout[] =
	{
		{ "POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0 },
		{ "TEXCOORD",0,DXGI_FORMAT_R32G32_FLOAT,0,16,D3D11_INPUT_PER_VERTEX_DATA,0 },
	};

	UINT numLayoutElements = ARRAYSIZE(solidColorLayout);
	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateInputLayout(solidColorLayout, numLayoutElements, vsBuffer->GetBufferPointer(),
		vsBuffer->GetBufferSize(), &m_pInputLayout);
	vsBuffer->Release();

	if (FAILED(result))
	{
		return false;
	}

	//几何shader

	ID3DBlob *gsBuffer = 0;
	compileResult = CompileD3DShader(L"ShaderSpher.fx", "GS_Main", "gs_4_0", &gsBuffer);
	if (!compileResult)
	{
		MessageBoxA(0, "几何着色器加载失败", "编译错误", MB_OK);
		return false;
	}

	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateGeometryShader(gsBuffer->GetBufferPointer(), gsBuffer->GetBufferSize(),
		0, &m_geometryShader);
	gsBuffer->Release();
	if (FAILED(result))
	{
		return false;
	}

	//载入像素着色器
	ID3DBlob *psBuffer = 0;
	compileResult = CompileD3DShader(L"ShaderSpher.fx", "PS_Main", "ps_4_0", &psBuffer);
	if (!compileResult)
	{
		MessageBoxA(0, "像素着色器加载失败", "编译错误", MB_OK);
		return false;
	}

	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreatePixelShader(psBuffer->GetBufferPointer(), psBuffer->GetBufferSize(),
		0, &m_pSolidColorPS);
	psBuffer->Release();
	if (FAILED(result))
	{
		return false;
	}


	//构造顶点
	vector<VertexSphere>VertexList;
	for (int i = 0; i < latitude; i++)
	{
		for (int j = 0; j < longitude; j++)
		{
			LL[i][j].lat = (float)(1.f / (latitude-1))*i;
			LL[i][j].lot = (float)(1.f / (longitude-1))*j;
			float x, y, z;
			y = DirectX::XMScalarSin(XM_PI / 2.f -LL[i][j].lat*XM_PI);
			x = DirectX::XMScalarCos(LL[i][j].lat*XM_PI - XM_PI / 2.f)*DirectX::XMScalarCos(LL[i][j].lot*XM_PI*2.f);
			z = DirectX::XMScalarCos(LL[i][j].lat*XM_PI - XM_PI / 2.f)*DirectX::XMScalarSin(LL[i][j].lot*XM_PI*2.f);
			VertexSphere SphereVertex;
			SphereVertex.pos = XMFLOAT4(x, y, z,1.f);
			SphereVertex.UV = XMFLOAT2(LL[i][j].lot, LL[i][j].lat);
			VertexList.push_back(SphereVertex);
		}
	}

	D3D11_BUFFER_DESC vertexDesc;
	ZeroMemory(&vertexDesc, sizeof(vertexDesc));
	vertexDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vertexDesc.ByteWidth = sizeof(VertexSphere) * VertexList.size();

	D3D11_SUBRESOURCE_DATA resourceData;
	ZeroMemory(&resourceData, sizeof(resourceData));
	resourceData.pSysMem = VertexList.data();

	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateBuffer(&vertexDesc, &resourceData, &m_pVertexBuffer);
	if (FAILED(result))
	{
		return false;
	}

	//构造Indexbuffer
	vector<WORD> indices;
	for (int i = 0; i < latitude-1; i++)
	{
		for (int j = 0; j < longitude-1; j++)
		{
			indices.push_back((i + 1)*longitude + (j + 1));
			indices.push_back((i + 1)*longitude + j);
			indices.push_back(i*longitude + j);
			indices.push_back(i*longitude + j);
			indices.push_back(i*longitude + j + 1);
			indices.push_back((i + 1)*longitude + j + 1);
		}
	}
	IndexCount = indices.size();
	D3D11_BUFFER_DESC vertexIndexDesc;
	ZeroMemory(&vertexIndexDesc, sizeof(vertexIndexDesc));
	vertexIndexDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexIndexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
	vertexIndexDesc.ByteWidth = sizeof(WORD) * indices.size();
	vertexIndexDesc.CPUAccessFlags = 0;

	D3D11_SUBRESOURCE_DATA IndexData;
	ZeroMemory(&IndexData, sizeof(IndexData));
	IndexData.pSysMem = indices.data();
	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateBuffer(&vertexIndexDesc, &IndexData, &m_pIndexBuffer);
	if (FAILED(result))
	{
		return false;
	}

	//Const Buffer

	D3D11_BUFFER_DESC cbDesc;
	ZeroMemory(&cbDesc, sizeof(D3D11_BUFFER_DESC));
	cbDesc.ByteWidth = sizeof(ConstSphereBuffer);
	cbDesc.Usage = D3D11_USAGE_DEFAULT;
	cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	cbDesc.CPUAccessFlags = 0;

	// Fill in the subresource data.
	//D3D11_SUBRESOURCE_DATA InitData;
	//InitData.pSysMem = &ConstBufferData;
	//InitData.SysMemPitch = 0;
	//InitData.SysMemSlicePitch = 0;

	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateBuffer(&cbDesc, nullptr,
		&g_pConstantBuffer11);
	if (FAILED(result))
	{
		MessageBoxA(0, 0, 0, 0);
		return false;
	}

	//贴图
	result = DXUTCreateShaderResourceViewFromFile(RenderManager::GetRenderManagerInstance()->GetD3DDeviece(), L"earth.gif", &g_pTextureRV);
	if (FAILED(result))
		return false;

	// Create the sample state
	D3D11_SAMPLER_DESC sampDesc;
	ZeroMemory(&sampDesc, sizeof(sampDesc));
	sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
	sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
	sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
	sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
	sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
	sampDesc.MinLOD = 0;
	sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateSamplerState(&sampDesc, &g_pSamplerLinear);
	if (FAILED(result))
		return false;


	//构建矩阵
	g_SphereWorld = XMMatrixIdentity();
	//XMVECTOR Eye = XMVectorSet(0.0f, 0.f, -30.f, 0.0f);
	//XMVECTOR At = XMVectorSet(0.0f, 0.f, 0.0f, 0.0f);
	//XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
	//g_SphereView = XMMatrixLookAtLH(Eye, At, Up);
	//g_SphereProjection = XMMatrixPerspectiveFovLH(XM_PIDIV2/6, 1024.f / 768.f, 0.01f, 100.0f);
	return true;
}

void SphereDemo::UnLoadContent()
{
	if (m_pSolidColorPS)
		m_pSolidColorPS->Release();
	if (m_pSolidColorVS)
		m_pSolidColorVS->Release();
	if (m_pVertexBuffer)
		m_pVertexBuffer->Release();
	if (m_pInputLayout)
		m_pInputLayout->Release();
	if (g_pConstantBuffer11)
		g_pConstantBuffer11->Release();
	if (m_pIndexBuffer)
		m_pIndexBuffer->Release();

	m_pSolidColorVS = 0;
	m_pSolidColorPS = 0;
	m_pVertexBuffer = 0;
	m_pInputLayout = 0;
	m_pIndexBuffer = nullptr;
	g_pConstantBuffer11 = nullptr;
}

void SphereDemo::Update(float dt)
{
	static float t = 0.0f;
	static ULONGLONG timeStart = 0;
	ULONGLONG timeCur = GetTickCount64();
	if (timeStart == 0)
		timeStart = timeCur;
	t = (timeCur - timeStart) / 1000.f;

	// Rotate cube around the origin

	
	XMFLOAT4 TransDir = { 0.f,0.f,1.f,1.f };
	XMMATRIX mRotate = XMMatrixRotationY(-t/2);
	XMVECTOR vTransDir = XMLoadFloat4(&TransDir);
	vTransDir = XMVector3Transform(vTransDir, mRotate);
	XMStoreFloat4(&TransDir, vTransDir);
    XMFLOAT3 normal(XMScalarSin(22.5/180*XM_PI), XMScalarCos(22.5 / 180 * XM_PI), 0);
	FXMVECTOR f = XMLoadFloat3(&normal);

	g_SphereWorld = XMMatrixRotationNormal(f, -6 * t)*XMMatrixTranslationFromVector(4.f*XMLoadFloat4(&TransDir));
	
}

void SphereDemo::Render()
{
	if (RenderManager::GetRenderManagerInstance()->GetImmediateContext() == 0)
		return;
	if (TheCamera == nullptr)
	{
		return;
	}

	//set no cull
	RenderManager::GetRenderManagerInstance()->SetNoCull(true);

	UINT stride = sizeof(VertexSphere);
	UINT offset = 0;
	//设置数据信息格式控制信息
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->IASetInputLayout(m_pInputLayout);
	//设置要绘制的几何体信息
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);

	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
	//指明如何绘制三角形
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	ConstSphereBuffer ConstBufferData;
	ConstBufferData.m_world = XMMatrixTranspose(g_SphereWorld); 
	if (TheCamera)
	{
		ConstBufferData.m_view = XMMatrixTranspose(TheCamera->GetView());
		ConstBufferData.m_proj = XMMatrixTranspose(TheCamera->GetProj());
	}
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->UpdateSubresource(
		g_pConstantBuffer11,
		0,
		nullptr,
		&ConstBufferData,
		0,
		0
		);
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->VSSetConstantBuffers(0, 1, &g_pConstantBuffer11);
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->VSSetShader(m_pSolidColorVS, 0, 0);
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->PSSetShader(m_pSolidColorPS, 0, 0);
	//RenderManager::GetRenderManagerInstance()->GetImmediateContext()->GSSetShader(m_geometryShader, 0, 0);
	//RenderManager::GetRenderManagerInstance()->GetImmediateContext()->GSSetConstantBuffers(0, 1, &g_pConstantBuffer11);
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->PSSetShaderResources(0, 1, &g_pTextureRV);
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->PSSetSamplers(0, 1, &g_pSamplerLinear);
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->DrawIndexed(IndexCount,0,0);
}
